home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Found / FWExcLib / Sources / FWExcRun.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  13.6 KB  |  422 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWExcRun.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    (c) 1993, 1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #ifndef FW_NATIVE_EXCEPTIONS
  13.  
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17. #ifndef   FWEXCRUN_H
  18. #include "FWExcRun.h"
  19. #endif
  20.  
  21. #ifndef   FWDELSTA_H
  22. #include "FWDelSta.h"
  23. #endif
  24.  
  25. #ifndef   FWTRYBLO_H
  26. #include "FWTryBlo.h"
  27. #endif
  28.  
  29. #ifndef   FWPRIDEB_H
  30. #include "FWPriDeb.h"
  31. #endif
  32.  
  33. #ifndef   FWPRIMEM_H
  34. #include "FWPriMem.h"
  35. #endif
  36.  
  37. #ifndef FWNEWHEL_H
  38. #include "FWNewHel.h"
  39. #endif
  40.  
  41. #ifndef   FWONSTAC_H
  42. #include "FWOnStac.h"
  43. #endif
  44.  
  45. #if defined FW_BUILD_WIN && defined __BORLANDC__
  46. #include <except.h>
  47. #endif
  48.  
  49. #if FW_LIB_EXPORT_PRAGMAS
  50. #pragma lib_export on
  51. #endif
  52.  
  53. #ifdef FW_BUILD_MAC
  54. #pragma segment FWExcLib
  55. #endif
  56.  
  57. //========================================================================================
  58. //    Functions for "unexpected" and "terminate"
  59. //
  60. //        See ARM, Section 15.6
  61. //========================================================================================
  62.  
  63. static void DefaultTerminate();
  64. static void DefaultUnexpected();
  65.  
  66. static void DefaultTerminate()
  67. {
  68.     abort();
  69. }
  70.  
  71. static void DefaultUnexpected()
  72. {
  73.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  74.     PFV pfCurrentTerminate = globals.gCurrentTerminate;
  75.     (*pfCurrentTerminate)();
  76. }
  77.  
  78. #if !defined(__BORLANDC__) && !defined(__MWERKS__)
  79. void terminate()
  80. {
  81.     FW_PRIV_DEBUGGER_BREAK();
  82.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  83.     PFV pfCurrentTerminate = globals.gCurrentTerminate;
  84.     (*pfCurrentTerminate)();
  85. }
  86.  
  87. void unexpected()
  88. {
  89.     FW_PRIV_DEBUGGER_BREAK();
  90.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  91.     PFV pfCurrentUnexpected = globals.gCurrentUnexpected;
  92.     (*pfCurrentUnexpected)();
  93. }
  94.  
  95. PFV set_terminate(PFV terminate)
  96. {
  97.     return FW_CPrivExceptionRuntime::SetTerminate(terminate);
  98. }
  99.  
  100. PFV set_unexpected(PFV unexpected)
  101. {
  102.     return FW_CPrivExceptionRuntime::SetUnexpected(unexpected);
  103. }
  104. #endif
  105.  
  106. #ifdef FW_BUILD_WIN32
  107. int _FW_PrivIsOnStack(void * p)
  108. {
  109.     // [KVV] This version of IsOnStack assumes that the stack is only 16K.
  110.     //    In reality, Windows NT allocates a much larger stack.
  111.  
  112.     char localVar;
  113.     return (&localVar < p) && (p <= &localVar + 16000);
  114. }
  115. #endif
  116.  
  117. #if GENERATINGCFM
  118. int _FW_PrivIsOnStack(void * p)
  119. {
  120.     char localVar;
  121.     return (&localVar < p) && (p < LMGetCurStackBase());
  122. }
  123. #endif
  124.  
  125. #ifdef __MWERKS__
  126.  
  127. const FW_CPrivNewHelper& _FW_MetrowerksHack(const FW_CPrivNewHelper&);
  128.  
  129. const FW_CPrivNewHelper& _FW_MetrowerksHack(const FW_CPrivNewHelper& helper)
  130. {
  131.     return helper;
  132. }
  133.  
  134. #endif
  135.  
  136. //========================================================================================
  137. // CLASS FW_CPrivExceptionRuntime
  138. //========================================================================================
  139.  
  140. //----------------------------------------------------------------------------------------
  141. // FW_CPrivExceptionRuntime::Initialize
  142. //----------------------------------------------------------------------------------------
  143. void FW_CPrivExceptionRuntime::Initialize(FW_SPrivExceptionGlobals& globals)
  144. {
  145.     globals.gExceptionBufferSize = kDefaultExceptionBufferSize;
  146.     globals.gExceptionBuffer = ::FW_PrimitiveAllocateBlock(kDefaultExceptionBufferSize);
  147.     globals.gCurrentTerminate = DefaultTerminate;
  148.     globals.gCurrentUnexpected = DefaultUnexpected;
  149.     
  150. #ifdef FW_DEBUG
  151.     SetBreakOnThrow(NULL);
  152. #endif
  153. }
  154.  
  155. //----------------------------------------------------------------------------------------
  156. // FW_CPrivExceptionRuntime::Terminate
  157. //----------------------------------------------------------------------------------------
  158. void FW_CPrivExceptionRuntime::Terminate()
  159. {
  160.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  161.     ::FW_PrimitiveFreeBlock(globals.gExceptionBuffer);
  162. }
  163.  
  164. //----------------------------------------------------------------------------------------
  165. // FW_CPrivExceptionRuntime::SetTerminate
  166. //----------------------------------------------------------------------------------------
  167. PFV FW_CPrivExceptionRuntime::SetTerminate(PFV newTerminate)
  168. {
  169.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  170.     PFV oldTerminate = globals.gCurrentTerminate;
  171.     globals.gCurrentTerminate = newTerminate;
  172.     return oldTerminate;
  173. }
  174.  
  175. //----------------------------------------------------------------------------------------
  176. // FW_CPrivExceptionRuntime::SetUnexpected
  177. //----------------------------------------------------------------------------------------
  178. PFV FW_CPrivExceptionRuntime::SetUnexpected(PFV newUnexpected)
  179. {
  180.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  181.     PFV oldUnexpected = globals.gCurrentUnexpected;
  182.     globals.gCurrentUnexpected = newUnexpected;
  183.     return oldUnexpected;
  184. }
  185.  
  186. //----------------------------------------------------------------------------------------
  187. // FW_CPrivExceptionRuntime::CaughtException
  188. //----------------------------------------------------------------------------------------
  189. void FW_CPrivExceptionRuntime::CaughtException(FW_SPrivExceptionGlobals& globals, _FW_XException * caughtException)
  190. {
  191.     globals.gThrownException->PrivDelete();
  192.     globals.gCaughtException = caughtException;
  193.     globals.gThrownException = NULL;
  194. }
  195.  
  196. //----------------------------------------------------------------------------------------
  197. // FW_CPrivExceptionRuntime::CaughtEverythingException
  198. //----------------------------------------------------------------------------------------
  199. void FW_CPrivExceptionRuntime::CaughtEverythingException(FW_SPrivExceptionGlobals& globals)
  200. {
  201.     globals.gCaughtException = globals.gThrownException;
  202.     globals.gThrownException = NULL;
  203. }
  204.  
  205. //----------------------------------------------------------------------------------------
  206. // FW_CPrivExceptionRuntime::CaughtNoInstanceException
  207. //----------------------------------------------------------------------------------------
  208. void FW_CPrivExceptionRuntime::CaughtNoInstanceException(FW_SPrivExceptionGlobals& globals)
  209. {
  210.     globals.gCaughtException = globals.gThrownException;
  211.     globals.gThrownException = NULL;
  212. }
  213.  
  214. //----------------------------------------------------------------------------------------
  215. // FW_CPrivExceptionRuntime::CaughtReferenceException
  216. //----------------------------------------------------------------------------------------
  217. void FW_CPrivExceptionRuntime::CaughtReferenceException(FW_SPrivExceptionGlobals& globals)
  218. {
  219.     globals.gCaughtException = globals.gThrownException;
  220.     globals.gThrownException = NULL;
  221. }
  222.  
  223. //----------------------------------------------------------------------------------------
  224. // FW_CPrivExceptionRuntime::PrimitiveThrow
  225. //----------------------------------------------------------------------------------------
  226.  
  227. void FW_CPrivExceptionRuntime::PrimitiveThrow(const _FW_XException & thrownException)
  228. {
  229.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  230.  
  231.     // Should never have an exception on the way in
  232.     FW_PRIV_ASSERT(globals.gThrownException == NULL);
  233.     
  234.     FW_CPrivTryBlockContext *context = globals.gCurrentContext;
  235.     FW_PRIV_ASSERT(context!=NULL);
  236.     if (context->fPriorContext == NULL)
  237.     {
  238.         terminate();
  239.         abort(); // Terminate should never return
  240.     }
  241.  
  242.     if (FW_CPrivDeleteStack::IsClassExpectedInContext(context, thrownException.PrivVirtualGetClassInfo()))
  243.     {
  244.         // If someone had caught an exception delete that exception
  245.         // because we are going to bypass the destructor for it.
  246.         if (globals.gCaughtException != NULL)
  247.         {
  248.             globals.gCaughtException->PrivDelete();
  249.             globals.gCaughtException = 0;
  250.         }
  251.  
  252.         // Copy the original into our exception buffer
  253.         thrownException.Copy(globals.gExceptionBuffer, globals.gExceptionBufferSize);
  254.  
  255.         // We have a thrown exception so point gThrownException at it.
  256.         globals.gThrownException = (_FW_XException*)globals.gExceptionBuffer;
  257.  
  258.         // We have copied the original so delete it.
  259.         ((_FW_XException &)thrownException).PrivDelete();
  260.  
  261.         DeleteObjectsInContextAndJump(globals, context);
  262.     }
  263.     else
  264.     {
  265.         unexpected();
  266.     }
  267. }
  268.  
  269. //----------------------------------------------------------------------------------------
  270. // FW_CPrivExceptionRuntime::PrimitiveThrowSame
  271. //----------------------------------------------------------------------------------------
  272.  
  273. void FW_CPrivExceptionRuntime::PrimitiveThrowSame()
  274. {
  275.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  276.  
  277.     FW_PRIV_ASSERT(globals.gCaughtException != NULL);
  278.     if (globals.gCaughtException == NULL)
  279.     {
  280.         abort();            // Can't throwsame if nothing is currently caught
  281.     }
  282.  
  283.     FW_CPrivTryBlockContext * context = globals.gCurrentContext;
  284.     FW_PRIV_ASSERT(context != NULL);
  285.     if (context->fPriorContext == NULL)
  286.     {
  287.         terminate();
  288.         abort();            // Terminate should never return but if it does we will abort
  289.     }
  290.  
  291.     _FW_XException *caughtException = globals.gCaughtException;
  292.  
  293.     if (FW_CPrivDeleteStack::IsClassExpectedInContext(context, caughtException->PrivVirtualGetClassInfo()))
  294.     {
  295.         if (caughtException != (_FW_XException *)globals.gExceptionBuffer)
  296.         {
  297.             // The exception is in the stack frame so copy it to our exception buffer,
  298.             // delete the original and then pass the copy along.
  299.             caughtException->Copy(globals.gExceptionBuffer, globals.gExceptionBufferSize);
  300.             caughtException->PrivDelete();
  301.             globals.gThrownException = (_FW_XException*)globals.gExceptionBuffer;
  302.         }
  303.         else
  304.         {
  305.             // The exception is already in our buffer
  306.             globals.gThrownException = (_FW_XException*)globals.gCaughtException;
  307.         }
  308.  
  309.         globals.gCaughtException = 0;
  310.  
  311.         DeleteObjectsInContextAndJump(globals, context);
  312.     }
  313.     else
  314.     {
  315.         unexpected();
  316.     }
  317. }
  318.  
  319. //----------------------------------------------------------------------------------------
  320. // FW_CPrivExceptionRuntime::Throw
  321. //----------------------------------------------------------------------------------------
  322. void FW_CPrivExceptionRuntime::Throw(const _FW_XException & thrownException)
  323. {
  324.     PrimitiveThrow(thrownException);
  325. }
  326.  
  327. //----------------------------------------------------------------------------------------
  328. // FW_CPrivExceptionRuntime::ThrowSame
  329. //----------------------------------------------------------------------------------------
  330. void FW_CPrivExceptionRuntime::ThrowSame()
  331. {
  332.     PrimitiveThrowSame();
  333. }
  334.  
  335. //----------------------------------------------------------------------------------------
  336. // FW_CPrivExceptionRuntime::ThrowConstructor
  337. //----------------------------------------------------------------------------------------
  338. void FW_CPrivExceptionRuntime::ThrowConstructor(_FW_XException & thrownException)
  339. {
  340.     PrimitiveThrow(thrownException);
  341. }
  342.  
  343. //----------------------------------------------------------------------------------------
  344. // FW_CPrivExceptionRuntime::ThrowSameConstructor
  345. //----------------------------------------------------------------------------------------
  346. void FW_CPrivExceptionRuntime::ThrowSameConstructor()
  347. {
  348.     PrimitiveThrowSame();
  349. }
  350.  
  351. //----------------------------------------------------------------------------------------
  352. // FW_CPrivExceptionRuntime::KeepThrowing
  353. //----------------------------------------------------------------------------------------
  354. void FW_CPrivExceptionRuntime::KeepThrowing(FW_SPrivExceptionGlobals& globals)
  355. {
  356.     FW_CPrivTryBlockContext *context = globals.gCurrentContext;
  357.     FW_PRIV_ASSERT(context!=NULL);
  358.     if (FW_CPrivDeleteStack::IsClassExpectedInContext(context, globals.gThrownException->PrivVirtualGetClassInfo()))
  359.     {
  360.         DeleteObjectsInContextAndJump(globals, context);
  361.     }
  362.     else
  363.     {
  364.         unexpected();
  365.     }
  366. }
  367.  
  368.  
  369. //----------------------------------------------------------------------------------------
  370. // FW_CPrivExceptionRuntime::ResetExceptionBufferSize
  371. //----------------------------------------------------------------------------------------
  372. void FW_CPrivExceptionRuntime::ResetExceptionBufferSize(size_t newSize)
  373. {
  374.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  375.     void *p = ::FW_PrimitiveResizeBlock(globals.gExceptionBuffer, newSize);
  376.     FW_PRIV_ASSERT(p != NULL);
  377.     globals.gExceptionBuffer = p;
  378.     globals.gExceptionBufferSize = newSize;
  379. }
  380.  
  381. //----------------------------------------------------------------------------------------
  382. // FW_CPrivExceptionRuntime::DeleteObjectsInContextAndJump
  383. //----------------------------------------------------------------------------------------
  384. void FW_CPrivExceptionRuntime::DeleteObjectsInContextAndJump(FW_SPrivExceptionGlobals& globals, 
  385.                                                         FW_CPrivTryBlockContext * context)
  386. {
  387. #ifdef FW_DEBUG
  388.     _FW_XException *thrownException = globals.gThrownException;
  389.     FW_ClassInfoPtr breakExceptionKind = globals.gBreakExceptionKind;
  390.     if (breakExceptionKind!=NULL && thrownException->PrivIsKindOf(breakExceptionKind))
  391.         FW_PRIV_DEBUGGER_STRING("Throwing an exception");
  392. #endif    
  393.     
  394.    FW_CPrivDeleteStack::PopOffAndDeleteObjectsInContext(globals, context);
  395.  
  396.     jmp_buf *jumpBuffer = context->fJumpBuffer;
  397. //    context->FW_CPrivTryBlockContext::~FW_CPrivTryBlockContext();
  398.     context->~FW_CPrivTryBlockContext();
  399.      ::longjmp(*jumpBuffer, 1);
  400. }
  401.  
  402.  
  403. //----------------------------------------------------------------------------------------
  404. // FW_CPrivExceptionRuntime::EndConstructor
  405. //----------------------------------------------------------------------------------------
  406. void FW_CPrivExceptionRuntime::EndConstructor(_FW_CAutoDestructObject *object, size_t size)
  407. {
  408.     if (_FW_PrivIsOnStack(object))
  409.         FW_CPrivDeleteStack::Push(object);
  410.  
  411. #ifdef FW_USE_NEW_HELPER
  412.     else
  413.     {
  414.         FW_CPrivNewHelper *helper = FW_CPrivNewHelper::TopNewHelper();
  415.         if (helper!=NULL && helper->IsWatching(object))
  416.             helper->UpdateForEndConstructor(object, size);
  417.     }
  418. #endif
  419. }
  420.  
  421. #endif // FW_NATIVE_EXCEPTIONS
  422.